package com.reguang.service.impl;

import java.util.Date;

import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.reguang.enums.ScopeEnum;
import com.reguang.enums.TimeEnum;
import com.reguang.exception.WeChatException;
import com.reguang.mapper.UserMapper;
import com.reguang.pojo.UserDO;
import com.reguang.service.UserService;
import com.reguang.user.config.WechatAccount;
import com.reguang.utils.HttpUtils;
import com.reguang.utils.ObjectUtils;
import com.reguang.utils.RedisOperator;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

	@Autowired
	private WechatAccount wechatAccount;

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private RedisOperator redisOperator;

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public String getToken(String code) throws Exception, WeChatException {
		String loginUrl = wechatAccount.getLoginUrl().replace("APPID", wechatAccount.getAppId()).// 小程序id
				replace("SECRET", wechatAccount.getAppSecret()).replace("JSCODE", code);
		JSONObject wxResult = HttpUtils.get(loginUrl);
		log.info("\n【请求微信返回结果】，result : {}", wxResult);
		if (ObjectUtils.isNull(wxResult)) {
			throw new WeChatException();
		} else {
			if (wxResult.containsKey("errcode")) {
				log.error("\n【请求微信返回错误结果】，result : {}", wxResult);
				throw new WeChatException();
			} else {
				return grantToken(wxResult);
			}
		}
	}

	/**
	 * 
	 * <p>Title: grantToken</p>
	 * <p>Description: 颁发令牌</p>
	 * @param wxResult
	 * @return
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	private String grantToken(JSONObject wxResult) {
		String openid = wxResult.getString("openid");
		UserDO record = new UserDO();
		record.setOpenid(openid);
		UserDO user = userMapper.selectOne(record);
		String userID = ObjectUtils.isNotNull(user) ? user.getId() : newUser(openid);
		JSONObject cachedValue = prepareCachedValue(wxResult, userID);
		return saveToCache(cachedValue);
	}

	/**
	 * 
	 * <p>Title: saveToCache</p>
	 * <p>Description: 写入缓存</p>
	 * @param cachedValue
	 * @return
	 */
	private String saveToCache(JSONObject cachedValue) {
		String key = Sid.next();
		redisOperator.set(key, cachedValue.toString(), Long.parseLong(TimeEnum.ONE_WEEK.sec().toString()));
		return key;
	}

	/**
	 * 
	 * <p>Title: newUser</p>
	 * <p>Description: 创建新用户</p>
	 * @param openid
	 * @return
	 */
	private String newUser(String openid) {
		UserDO user = new UserDO();
		user.setId(Sid.nextShort());
		user.setOpenid(openid);
		user.setCreateTime(new Date());
		userMapper.insert(user);
		return user.getId();
	}

	/**
	 * 
	 * <p>Title: prepareCachedValue</p>
	 * <p>Description: 准备缓存数据</p>
	 * @param wxResult
	 * @param userID
	 * @return
	 */
	private JSONObject prepareCachedValue(JSONObject wxResult, String userID) {
		wxResult.put("uid", userID);
		wxResult.put("scope", ScopeEnum.USER.code());
		return wxResult;
	}
}
